#include <shadow.h>
#include "../include/head.h"
#include <crypt.h>

static pthread_mutex_t getspname_mutex = PTHREAD_MUTEX_INITIALIZER;

typedef struct logTrain_s{
    int length;
    char data[1000];
}logTrain_t;

void get_salt(char *salt,char *psdp)
{ 
    int i = 0;
    int count = 0;
    while(psdp[i] && count < 4)
    { 
        if(psdp[i] == '$')
        { 
            count++;
        }
        i++;
    }
    strncpy(salt,psdp,i);
    /* printf("getsysSlat = %s\n",salt);//测试 */
}

int login(int sockfd,uid_t *uid)
{ 
    logTrain_t train;
    int login_success = 0;
    char userNameBuf[1024] ={0};
    while(login_success == 0){  
        bzero(&train,sizeof(train));
        recv(sockfd,&train.length,sizeof(train.length),0);
        recv(sockfd,train.data,train.length,0);
        strncpy(userNameBuf,train.data,sizeof(userNameBuf)-1);
        userNameBuf[sizeof(userNameBuf)-1] = '\0';

        struct spwd* userInfo = NULL;
        
        pthread_mutex_lock(&getspname_mutex);
        userInfo = getspnam(userNameBuf);
        pthread_mutex_unlock(&getspname_mutex);

        if(userInfo == NULL){ 
            char noName[] = "用户不存在！";
            train.length = strlen(noName)+ 1;
            strcpy(train.data,noName);
            send(sockfd,&train.length,sizeof(train.length),0);
            send(sockfd,train.data,train.length,0);
            continue;
        } else{ 
            char noName[] = "用户存在！";
            train.length = strlen(noName)+ 1;
            strcpy(train.data,noName);
            send(sockfd,&train.length,sizeof(train.length),0);
            send(sockfd,train.data,train.length,0);
            
            //循环发送盐值
            int pswd_succ = 0;
            int try_count = 0;
            const int MAX_TYR = 5;

            while(pswd_succ == 0 && try_count <MAX_TYR){ 
                
                try_count++;

                char salt[1024];
                get_salt(salt,userInfo->sp_pwdp);

                /* char *sysCrypt = crypt("1234",salt); */
                /* printf("%s\n",sysCrypt); */

                train.length = strlen(salt)+1;
                strcpy(train.data,salt);
                send(sockfd,&train.length,sizeof(train.length),0);
                send(sockfd,train.data,train.length,0);

                struct timeval timeout ={15,0};
                setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));
                
                //接收用户发来的自己加密的密文
                bzero(&train,sizeof(train));                     
                char new_crypt[4096] = {0};
                int ret =  recv(sockfd,&train.length,sizeof(train.length),0);
                if(ret <= 0)
                { 
                    printf("接收密码超时或错误\n");
                    break;
                }
                int  ret_data = recv(sockfd,train.data,train.length,0);
                if(ret_data <= 0)
                { 
                    printf("接收密码超时或错误\n");
                    break;
                }

                timeout.tv_sec = 0;
                setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,&timeout,sizeof(timeout));

                strcpy(new_crypt,train.data);
                
                /* printf("new_crypt =%s\n",new_crypt);//测试 */
                if(strcmp(new_crypt,userInfo->sp_pwdp) == 0){ 
                    //说明用户名和密码正确，建立连接
                    char sucMsg[] = "登陆成功！";
                    strcpy(train.data,sucMsg);
                    train.length = strlen(sucMsg)+1;
                    send(sockfd,&train.length,sizeof(train.length),0);
                    send(sockfd,train.data,train.length,0);
                        
                    struct passwd *pwd = getpwnam(userNameBuf);
                    *uid = pwd->pw_uid;

                    login_success = 1;
                    pswd_succ = 1;
                    return 1;

                } else{ 
                    //说明密码不正确，登陆失败
                    char failMsg[] = "登陆失败！";
                    strcpy(train.data,failMsg);
                    train.length = strlen(failMsg)+1;
                    send(sockfd,&train.length,sizeof(train.length),0);
                    send(sockfd,train.data,train.length,0);
                }
            }
            if(pswd_succ == 0)
            { 
                char maxTryMsg[] = "尝试次数用尽！";
                train.length = strlen(maxTryMsg);
                strcpy(train.data,maxTryMsg);
                send(sockfd,&train.length,sizeof(train.length),0);
                send(sockfd,train.data,train.length,0);
            }
        }
    }
    return 0;
}

/* int main(int argc,char *argv[]) */
/* { */ 
/*     ARGS_CHECK(argc,3); */
/*     int sockfd = socket(AF_INET,SOCK_STREAM,0); */
/*     struct sockaddr_in addr; */
/*     addr.sin_family = AF_INET; */
/*     addr.sin_port = htons(atoi(argv[2])); */
/*     addr.sin_addr.s_addr = inet_addr(argv[1]); */

/*     int flag = 1; */
/*     setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&flag,sizeof(flag)); */
/*     int ret =  bind(sockfd,(struct sockaddr*)&addr,sizeof(addr)); */
/*     ERROR_CHECK(ret,-1,"bind"); */
/*     listen(sockfd,50); */
/*     int netfd = accept(sockfd,NULL,NULL); */
/*     uid_t uid = getuid(); */
/*     login(netfd,&uid); */
/*     close(netfd); */

/*    return 0; */
/* } */
